package com.chensi.admin.userservice.aspect;

import com.chensi.admin.userservice.common.BaseErrorCode;
import com.chensi.admin.userservice.common.JsonResult;
import com.chensi.admin.userservice.exception.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.util.Optional;

/**
 * 全局异常处理
 *
 * @author si.chen
 * @date 2019/6/18
 */
@ControllerAdvice
@ResponseBody
@Slf4j
public class ExceptionAspect {

    /**
     * base异常
     */
    @ExceptionHandler(BaseException.class)
    @ResponseStatus(HttpStatus.OK)
    public JsonResult handleBaseException(BaseException e) {
        return JsonResult.failed(e.getErrorCode(), e.getErrorMessage(), e.getMessage());
    }

    /**
     * 所有其它异常
     */
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public JsonResult handleException(Exception e) {
        log.error("handler exception", e);
        e.printStackTrace();
        return JsonResult.failed(BaseErrorCode.UNKNOWN_EXCEPTION.getCode(),
                BaseErrorCode.UNKNOWN_EXCEPTION.getMessage(),
                e.getMessage());
    }

    /**
     * 数据绑定校验异常
     */
    @ExceptionHandler(BindException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public JsonResult handleConstraintViolationException(BindException e) {
        BindingResult result = e.getBindingResult();
        return toJsonResult(result);
    }

    /**
     * 参数校验异常
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public JsonResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        BindingResult result = e.getBindingResult();
        return toJsonResult(result);
    }

    /**
     * 非法参数
     */
    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public JsonResult handleIllegalArgumentException(IllegalArgumentException e) {
        log.error("handler exception", e);
        return JsonResult.failed(BaseErrorCode.INVALID_PARAMETERS.getCode(),
                BaseErrorCode.INVALID_PARAMETERS.getMessage(),
                e.getMessage());
    }

    /**
     * 非法参数
     */
    @ExceptionHandler(InvalidDataAccessApiUsageException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public JsonResult handleInvalidDataAccessApiUsageException(InvalidDataAccessApiUsageException e) {
        log.error("handler exception", e);
        return JsonResult.failed(BaseErrorCode.INVALID_PARAMETERS.getCode(),
                BaseErrorCode.INVALID_PARAMETERS.getMessage(),
                e.getMessage());
    }

    /**
     * requestParam参数丢失异常
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public JsonResult handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
        log.error("handler exception", e);
        return JsonResult.failed(BaseErrorCode.MISS_PARAMETERS.getCode(),
                BaseErrorCode.MISS_PARAMETERS.getMessage(),
                e.getMessage());
    }


    private JsonResult toJsonResult(BindingResult result) {
        FieldError fieldError = result.getFieldError();
        String desc = Optional.ofNullable(fieldError).map(FieldError::getDefaultMessage).orElse(null);
        return JsonResult.failed(BaseErrorCode.INVALID_PARAMETERS.getCode(),
                desc,
                BaseErrorCode.INVALID_PARAMETERS.getMessage());
    }

}
